#define _GNU_SOURCE

#include "app_device.h"
#include "log/log.h"
#include <fcntl.h>
#include <unistd.h>
#include "app_pool.h"
#include "app_mqtt.h"
#include "app_message.h"
#include "app_common.h"
#include <stdlib.h>

/* 上下游缓冲区大小 */
#define BUFFER_SIZE 1024
/* 线程池的大小 */
#define POOL_SIZE 5
/* 存放数据的容器大小 */
#define DATA_BUF_SIZE 128
#define WRITE_INTERVAL_MS 200

static Device *device = NULL;      // 单例模式

/* 临时时间 */
long temp_time = 0;
static int write_task_func(void *arg){
    // 从下行缓冲中读取出一个字符数组消息  app_buffer_read(down_buffer)
    char data_buffer[DATA_BUF_SIZE];
    int len = app_buffer_read(device->down_buffer, data_buffer, DATA_BUF_SIZE);

    if (len > 0 && device->pre_write)
    {
        // 将字符数组消息转换为蓝牙需要的格式数据  pre_write()
        len = device->pre_write(data_buffer, len);

        if (len > 0)
        {
            // 写之前，需要保证与上次写入的时间间隔不小于WRITE_INTERVAL_MS
            long current_time = app_common_GetCurrentTime();
            long interval = current_time - temp_time;
            if (interval < WRITE_INTERVAL_MS)
            {
                temp_time = current_time + WRITE_INTERVAL_MS - interval;
                // 休眠
                usleep((WRITE_INTERVAL_MS - interval) * 1000);
            }else {
                temp_time = current_time;
            }

            // 将数据保存到蓝牙对应的串口文件中，传递给下游设备 write(fd)
            int write_len = write(device->fd, data_buffer, len);
            if (write_len != len)
            {
                log_error("write error");
                return -1;
            }
            // 记录最后一次写入的时间
            device->last_write_time = temp_time;
            log_debug("write success");
            log_debug("write data: %s", app_common_charsToHexstr(data_buffer, len));

            return 0;
        }
    }
    
    return -1;
}

static int send_task_func(void *arg){
    // 从上行缓冲中读取出一个字符数组消息
    char data_buffer[DATA_BUF_SIZE];
    int len = app_buffer_read(device->up_buffer, data_buffer, DATA_BUF_SIZE);
    // 将字符数组消息转换为json格式消息
    char *json = app_message_charsToJson(data_buffer, len);
    // 将json消息发送给远程
    int result = app_mqtt_send(json);
    if (result == -1)
    {
        log_error("send message to remote failed");
        return -1;
    }
    log_debug("send message to remote success");
    log_debug("send message: %s", json);

    return 0;
}

int receive_msg_callback(char *json){
    // 将json格式消息转换为字符数组消息
    char data_buffer[DATA_BUF_SIZE];
    int len = app_message_jsonToChars(json, data_buffer, DATA_BUF_SIZE);
    // 将字符数组消息保存到下行缓冲中
    app_buffer_write(device->down_buffer, data_buffer, len);
    // 将消息数据保存到设备文件的任务交给线程池执行 app_pool_regiserTask(write_task_func)
    app_pool_registerTask(write_task_func, NULL);

    // return 0;
}

static void *read_thread_fuc(void *arg){
    // 不断读取下流设备通过蓝牙连接传输过来的数据
    while (device->is_running) {
        char data_buffer[DATA_BUF_SIZE];
        int len = read(device->fd, data_buffer, DATA_BUF_SIZE);

        /* 测试 */
        log_debug("len = ",len);
        if (len > 0 && device->post_read)
        {
            // 对蓝牙数据进行处理转换为字符数组消息
            len = device->post_read(data_buffer, len);
            if (len > 0)
            {
                // 将字符数组消息保存到上行缓冲区
                app_buffer_write(device->up_buffer, data_buffer, len);
                // 将发消息数据到远程的任务交给线程池执行
                app_pool_registerTask(send_task_func, NULL);
            } 
        }
    }
}

Device *app_device_init(char *filename)
{
    if (device) {
        return device;
    }
    device = (Device *)malloc(sizeof(Device));

    device->filename = filename;
    device->fd = open(filename, O_RDWR);
    device->is_running = false;
    device->up_buffer = app_buffer_init(BUFFER_SIZE);
    device->down_buffer = app_buffer_init(BUFFER_SIZE);
    device->last_write_time = 0;
    device->post_read = NULL;
    device->pre_write = NULL;

    // 初始化相关模块
    app_pool_init(POOL_SIZE);
    app_mqtt_init();

    return device;
}

int app_device_start(void)
{
    if (device->is_running)
    {
        log_debug("device is running");
        return 0;
    }
    device->is_running = 1;
    
    // 上行程序操作流程
    // 启动读取下游设备线程的线程，在线程函数中
    pthread_create(&device->read_thread, NULL, read_thread_fuc, NULL);

    // 下行程序操作流程
    // 注册接收远程消息的回调函数
    app_mqtt_registerRcvCallback(receive_msg_callback);

    return 0;
}

void app_device_destroy(void)
{
    device->is_running = 0;
    pthread_cancel(device->read_thread);
    close(device->fd);
    app_buffer_free(device->down_buffer);
    app_buffer_free(device->up_buffer);
    device->post_read = NULL;
    device->pre_write = NULL;
    device->last_write_time = 0;
    // free(device);

    // 关闭相关模块
    app_mqtt_close();
    app_pool_close();
}
